readback!
This commit is contained in:
@@ -14,11 +14,12 @@
|
|||||||
# import sys
|
# import sys
|
||||||
# sys.path.insert(0, os.path.abspath('.'))
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
project = 'PeakRDL-regblock'
|
project = 'PeakRDL-regblock'
|
||||||
copyright = '2021, Alex Mykyta'
|
copyright = '%d, Alex Mykyta' % datetime.datetime.now().year
|
||||||
author = 'Alex Mykyta'
|
author = 'Alex Mykyta'
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
|||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
#
|
#
|
||||||
html_theme = 'alabaster'
|
html_theme = "sphinx_rtd_theme"
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
|||||||
@@ -84,22 +84,13 @@ Dev Todo list
|
|||||||
I shouldn't have to go to the hwif or whatever
|
I shouldn't have to go to the hwif or whatever
|
||||||
dereferencer should have all the query functions
|
dereferencer should have all the query functions
|
||||||
|
|
||||||
- readback mux
|
|
||||||
|
|
||||||
- Start a sphinx docs thing
|
- Start a sphinx docs thing
|
||||||
I need to keep better track of everything!
|
I need to keep better track of everything!
|
||||||
Diagrams of each layer in an architecture overview
|
Diagrams of each layer in an architecture overview
|
||||||
transcribe logbook into dev notes
|
transcribe logbook into dev notes
|
||||||
|
|
||||||
- Am i doing msb/lsb correctly?
|
Define strict interface expectations for each layer!
|
||||||
bit ordering:
|
Including latency/etc
|
||||||
fields are always [msb:lsb]
|
|
||||||
but could be [low:high] or [high:low]
|
|
||||||
But how does this affect bus <-> field mapping though??
|
|
||||||
- [low:high] means that bit order gets swapped from the bus
|
|
||||||
- [high:low] means bit order is sliced naturally
|
|
||||||
DONE
|
|
||||||
|
|
||||||
|
|
||||||
endianness controls byte order of the CPU bus
|
endianness controls byte order of the CPU bus
|
||||||
controls byteswap at the CPUIF layer
|
controls byteswap at the CPUIF layer
|
||||||
@@ -119,3 +110,7 @@ Do something about cpuif byte strobes?
|
|||||||
Generate these in the io struct? I forget what I decided
|
Generate these in the io struct? I forget what I decided
|
||||||
|
|
||||||
- dereferencer has some remaining todos that depend on field logic
|
- dereferencer has some remaining todos that depend on field logic
|
||||||
|
|
||||||
|
- FIXME: cpuif reset inside top-level addrmap results in two input signals:
|
||||||
|
- one popped out to top
|
||||||
|
- another inside the input struct
|
||||||
|
|||||||
@@ -96,7 +96,9 @@ X If a node ispresent=true, and any of it's properties are a reference,
|
|||||||
y->we = y;
|
y->we = y;
|
||||||
... it works, but should it be allowed? Seems like user-error
|
... it works, but should it be allowed? Seems like user-error
|
||||||
|
|
||||||
|
! Signals marked as field_reset or cpuif_reset need to have activehigh/activelow
|
||||||
|
specified. (8.2.1-d states that activehigh/low does not have an implied default state if unset!)
|
||||||
|
Also aplies to signals referenced by fieldreset
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -109,19 +111,27 @@ List of stuff in case I forget.
|
|||||||
! = No! exporter does not enforce this yet
|
! = No! exporter does not enforce this yet
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
X Contents of target are all internal. No external regs
|
||||||
|
|
||||||
|
X Does not contain any mem components
|
||||||
|
|
||||||
|
X Warn/error on any signal with cpuif_reset set, that is not in the top-level
|
||||||
|
addrmap. At the very least, warn that it will be ignored
|
||||||
|
|
||||||
|
|
||||||
! "bridge" addrmap not supported
|
! "bridge" addrmap not supported
|
||||||
export shall refuse to process an addrmap marked as a "bridge"
|
export shall refuse to process an addrmap marked as a "bridge"
|
||||||
Only need to check top-level. Compiler will enforce that child nodes arent bridges
|
Only need to check top-level. Compiler will enforce that child nodes arent bridges
|
||||||
|
|
||||||
cpuif_resets
|
|
||||||
! Warn/error on any signal with cpuif_reset set, that is not in the top-level
|
|
||||||
addrmap. At the very least, warn that it will be ignored
|
|
||||||
|
|
||||||
! async data signals
|
! async data signals
|
||||||
Only supporting async signals if they are exclusively used in resets.
|
Only supporting async signals if they are exclusively used in resets.
|
||||||
Anyhting else declared as "async" shall be an error
|
Anyhting else declared as "async" shall be an error
|
||||||
I have zero interest in implementing resynchronizers
|
I have zero interest in implementing resynchronizers
|
||||||
|
|
||||||
|
! Error if a property references a non-signal component, or property reference from
|
||||||
|
outside the export hierarchy
|
||||||
|
|
||||||
! regwidth/accesswidth is sane
|
! regwidth/accesswidth is sane
|
||||||
! accesswidth == regwidth
|
! accesswidth == regwidth
|
||||||
Enforce this for now. Dont feel like supporting fancy modes yet
|
Enforce this for now. Dont feel like supporting fancy modes yet
|
||||||
@@ -135,9 +145,6 @@ cpuif_resets
|
|||||||
For now, probably limit to only allow the same regwidth everywhere?
|
For now, probably limit to only allow the same regwidth everywhere?
|
||||||
|
|
||||||
|
|
||||||
! Contents of target are all internal. No external regs
|
|
||||||
! Does not contain any mem components
|
|
||||||
|
|
||||||
! Do not allow unaligned addresses
|
! Do not allow unaligned addresses
|
||||||
All offsets & strides shall be a multiple of the regwidth used
|
All offsets & strides shall be a multiple of the regwidth used
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Downstream Signals:
|
|||||||
- cpuif_addr
|
- cpuif_addr
|
||||||
Byte address
|
Byte address
|
||||||
- cpuif_wr_data
|
- cpuif_wr_data
|
||||||
- cpuif_wr_bitstrb
|
- cpuif_wr_biten
|
||||||
per-bit strobes
|
per-bit strobes
|
||||||
some protocols may opt to tie this to all 1's
|
some protocols may opt to tie this to all 1's
|
||||||
- cpuif_rd_ack
|
- cpuif_rd_ack
|
||||||
|
|||||||
1
doc/requirements.txt
Normal file
1
doc/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pygments-systemrdl
|
||||||
223
hand-coded.sv
223
hand-coded.sv
@@ -1,223 +0,0 @@
|
|||||||
// Hand-coded demo. Not auto-generated
|
|
||||||
|
|
||||||
package top_pkg;
|
|
||||||
|
|
||||||
// top.whee[][].y
|
|
||||||
typedef struct {
|
|
||||||
logic value;
|
|
||||||
} top__wheexx__y__out_t;
|
|
||||||
|
|
||||||
// top.whee[][]
|
|
||||||
typedef struct {
|
|
||||||
top__wheexx__y__out_t y;
|
|
||||||
} top__wheexx__out_t;
|
|
||||||
|
|
||||||
// top.asdf[].aaa[].abc
|
|
||||||
typedef struct {
|
|
||||||
logic [14:0] value;
|
|
||||||
} top__asdfx__aaax__abc__out_t;
|
|
||||||
|
|
||||||
// top.asdf[].aaa[].def
|
|
||||||
typedef struct {
|
|
||||||
logic [3:0] value;
|
|
||||||
} top__asdfx__aaax__def__out_t;
|
|
||||||
|
|
||||||
// top.asdf[].aaa[]
|
|
||||||
typedef struct {
|
|
||||||
top__asdfx__aaax__abc__out_t abc;
|
|
||||||
top__asdfx__aaax__def__out_t def;
|
|
||||||
} top__asdfx__aaax__out_t;
|
|
||||||
|
|
||||||
// top.asdf[].bbb.abc
|
|
||||||
typedef struct {
|
|
||||||
logic value;
|
|
||||||
} top__asdfx__bbb__abc__out_t;
|
|
||||||
|
|
||||||
// top.asdf[].bbb.def
|
|
||||||
typedef struct {
|
|
||||||
logic value;
|
|
||||||
} top__asdfx__bbb__def__out_t;
|
|
||||||
|
|
||||||
// top.asdf[].bbb
|
|
||||||
typedef struct {
|
|
||||||
top__asdfx__bbb__abc__out_t abc;
|
|
||||||
top__asdfx__bbb__def__out_t def;
|
|
||||||
} top__asdfx__bbb__out_t;
|
|
||||||
|
|
||||||
// top.asdf[]
|
|
||||||
typedef struct {
|
|
||||||
top__asdfx__aaax__out_t aaa[4];
|
|
||||||
top__asdfx__bbb__out_t bbb;
|
|
||||||
} top__asdfx__out_t;
|
|
||||||
|
|
||||||
// top
|
|
||||||
typedef struct {
|
|
||||||
top__wheexx__out_t whee[2][8];
|
|
||||||
top__asdfx__out_t asdf[20];
|
|
||||||
} top__out_t;
|
|
||||||
|
|
||||||
endpackage
|
|
||||||
|
|
||||||
module top #(
|
|
||||||
// TODO: pipeline parameters
|
|
||||||
)(
|
|
||||||
input wire clk,
|
|
||||||
input wire rst,
|
|
||||||
|
|
||||||
|
|
||||||
apb4_intf.slave s_apb,
|
|
||||||
|
|
||||||
output top_pkg::top__out_t hwif_out
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam ADDR_WIDTH = 32;
|
|
||||||
localparam DATA_WIDTH = 32;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
// CPU Bus interface logic
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
logic cpuif_req;
|
|
||||||
logic cpuif_req_is_wr;
|
|
||||||
logic [ADDR_WIDTH-1:0] cpuif_addr;
|
|
||||||
logic [DATA_WIDTH-1:0] cpuif_wr_data;
|
|
||||||
logic [DATA_WIDTH-1:0] cpuif_wr_bitstrb;
|
|
||||||
|
|
||||||
logic cpuif_rd_ack;
|
|
||||||
logic [DATA_WIDTH-1:0] cpuif_rd_data;
|
|
||||||
logic cpuif_rd_err;
|
|
||||||
|
|
||||||
logic cpuif_wr_ack;
|
|
||||||
logic cpuif_wr_err;
|
|
||||||
|
|
||||||
begin
|
|
||||||
// Request
|
|
||||||
logic is_active;
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
is_active <= '0;
|
|
||||||
cpuif_req <= '0;
|
|
||||||
cpuif_req_is_wr <= '0;
|
|
||||||
cpuif_addr <= '0;
|
|
||||||
cpuif_wr_data <= '0;
|
|
||||||
cpuif_wr_bitstrb <= '0;
|
|
||||||
end else begin
|
|
||||||
if(~is_active) begin
|
|
||||||
if(s_apb.psel) begin
|
|
||||||
is_active <= '1;
|
|
||||||
cpuif_req <= '1;
|
|
||||||
cpuif_req_is_wr <= s_apb.pwrite;
|
|
||||||
cpuif_addr <= s_apb.paddr[ADDR_WIDTH-1:0];
|
|
||||||
cpuif_wr_data <= s_apb.pwdata;
|
|
||||||
for(int i=0; i<DATA_WIDTH/8; i++) begin
|
|
||||||
cpuif_wr_bitstrb[i*8 +: 8] <= {8{s_apb.pstrb[i]}};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
cpuif_req <= '0;
|
|
||||||
if(cpuif_rd_ack || cpuif_wr_ack) begin
|
|
||||||
is_active <= '0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// Response
|
|
||||||
assign s_apb.pready = cpuif_rd_ack | cpuif_wr_ack;
|
|
||||||
assign s_apb.prdata = cpuif_rd_data;
|
|
||||||
assign s_apb.pslverr = cpuif_rd_err | cpuif_wr_err;
|
|
||||||
end
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
// Address Decode
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
typedef struct {
|
|
||||||
logic whee[2][8];
|
|
||||||
struct {
|
|
||||||
logic aaa[4];
|
|
||||||
logic bbb;
|
|
||||||
} asdf[20];
|
|
||||||
} access_strb_t;
|
|
||||||
access_strb_t access_strb;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
for(int i0=0; i0<2; i0++) begin
|
|
||||||
for(int i1=0; i1<8; i1++) begin
|
|
||||||
access_strb.whee[i0][i1] = cpuif_req & (cpuif_addr == 'h0 + i0*'h20 + i1*'h4);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for(int i0=0; i0<20; i0++) begin
|
|
||||||
for(int i1=0; i1<4; i1++) begin
|
|
||||||
access_strb.asdf[i0].aaa[i1] = cpuif_req & (cpuif_addr == 'h40 + i0*'h14 + i1*'h4);
|
|
||||||
end
|
|
||||||
access_strb.asdf[i0].bbb = cpuif_req & (cpuif_addr == 'h50 + i0*'h14);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// Writes are always posted with no error response
|
|
||||||
assign cpuif_wr_ack = cpuif_req & cpuif_req_is_wr;
|
|
||||||
assign cpuif_wr_err = '0;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
// Field logic
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
typedef struct {
|
|
||||||
struct {
|
|
||||||
logic y;
|
|
||||||
} whee[2][8];
|
|
||||||
struct {
|
|
||||||
struct {
|
|
||||||
logic [14:0] abc;
|
|
||||||
logic [3:0] def;
|
|
||||||
} aaa[4];
|
|
||||||
struct {
|
|
||||||
logic abc;
|
|
||||||
logic def;
|
|
||||||
} bbb;
|
|
||||||
} asdf[20];
|
|
||||||
} field_storage_t;
|
|
||||||
field_storage_t field_storage;
|
|
||||||
|
|
||||||
// TODO: Field next-state logic, and output port signal assignment (aka output mapping layer)
|
|
||||||
TODO:
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
// Readback mux
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
logic readback_err;
|
|
||||||
logic [DATA_WIDTH-1:0] readback_data;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
readback_err = '0;
|
|
||||||
readback_data = '0;
|
|
||||||
if(cpuif_req & ~cpuif_req_is_wr) begin
|
|
||||||
readback_err = '1;
|
|
||||||
for(int i0=0; i0<2; i0++) begin
|
|
||||||
for(int i1=0; i1<8; i1++) begin
|
|
||||||
if(cpuif_addr == 'h0 + i0*'h20 + i1*'h4) begin
|
|
||||||
readback_err = '0;
|
|
||||||
readback_data[0:0] = field_storage.whee[i0][i1].y;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for(int i0=0; i0<20; i0++) begin
|
|
||||||
for(int i1=0; i1<4; i1++) begin
|
|
||||||
if(cpuif_addr == 'h40 + i0*'h14 + i1*'h4) begin
|
|
||||||
readback_err = '0;
|
|
||||||
readback_data[16:2] = field_storage.asdf[i0].aaa[i1].abc;
|
|
||||||
readback_data[4:4] = field_storage.asdf[i0].aaa[i1].def;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if(cpuif_addr == 'h50 + i0*'h14) begin
|
|
||||||
readback_err = '0;
|
|
||||||
readback_data[0:0] = field_storage.asdf[i0].bbb.abc;
|
|
||||||
readback_data[1:1] = field_storage.asdf[i0].bbb.def;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign cpuif_rd_ack = cpuif_req & ~cpuif_req_is_wr;
|
|
||||||
assign cpuif_rd_data = readback_data;
|
|
||||||
assign cpuif_rd_err = readback_err;
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
{% block body %}
|
{% block body %}
|
||||||
// Request
|
// Request
|
||||||
logic is_active;
|
logic is_active;
|
||||||
always_ff {{get_always_ff_event(cpuif_reset)}} begin
|
always_ff {{get_always_ff_event(cpuif.reset)}} begin
|
||||||
if({{cpuif_reset.activehigh_identifier}}) begin
|
if({{cpuif.reset.activehigh_identifier}}) begin
|
||||||
is_active <= '0;
|
is_active <= '0;
|
||||||
cpuif_req <= '0;
|
cpuif_req <= '0;
|
||||||
cpuif_req_is_wr <= '0;
|
cpuif_req_is_wr <= '0;
|
||||||
@@ -16,7 +16,11 @@ always_ff {{get_always_ff_event(cpuif_reset)}} begin
|
|||||||
is_active <= '1;
|
is_active <= '1;
|
||||||
cpuif_req <= '1;
|
cpuif_req <= '1;
|
||||||
cpuif_req_is_wr <= {{cpuif.signal("pwrite")}};
|
cpuif_req_is_wr <= {{cpuif.signal("pwrite")}};
|
||||||
cpuif_addr <= {{cpuif.signal("paddr")}}[ADDR_WIDTH-1:0];
|
{%- if cpuif.data_width == 8 %}
|
||||||
|
cpuif_addr <= {{cpuif.signal("paddr")}}[{{cpuif.addr_width-1}}:0];
|
||||||
|
{%- else %}
|
||||||
|
cpuif_addr <= { {{-cpuif.signal("paddr")}}[{{cpuif.addr_width-1}}:{{clog2(cpuif.data_width//8)}}], {{clog2(cpuif.data_width//8)}}'b0};
|
||||||
|
{%- endif %}
|
||||||
cpuif_wr_data <= {{cpuif.signal("pwdata")}};
|
cpuif_wr_data <= {{cpuif.signal("pwdata")}};
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
@@ -27,7 +31,7 @@ always_ff {{get_always_ff_event(cpuif_reset)}} begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assign cpuif_wr_bitstrb = '0;
|
assign cpuif_wr_biten = '1;
|
||||||
|
|
||||||
// Response
|
// Response
|
||||||
assign {{cpuif.signal("pready")}} = cpuif_rd_ack | cpuif_wr_ack;
|
assign {{cpuif.signal("pready")}} = cpuif_rd_ack | cpuif_wr_ack;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from ..utils import get_always_ff_event
|
from ..utils import get_always_ff_event, clog2
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..exporter import RegblockExporter
|
from ..exporter import RegblockExporter
|
||||||
@@ -11,7 +11,7 @@ class CpuifBase:
|
|||||||
|
|
||||||
def __init__(self, exp:'RegblockExporter', cpuif_reset:'SignalBase', data_width:int=32, addr_width:int=32):
|
def __init__(self, exp:'RegblockExporter', cpuif_reset:'SignalBase', data_width:int=32, addr_width:int=32):
|
||||||
self.exp = exp
|
self.exp = exp
|
||||||
self.cpuif_reset = cpuif_reset
|
self.reset = cpuif_reset
|
||||||
self.data_width = data_width
|
self.data_width = data_width
|
||||||
self.addr_width = addr_width
|
self.addr_width = addr_width
|
||||||
|
|
||||||
@@ -22,10 +22,8 @@ class CpuifBase:
|
|||||||
def get_implementation(self) -> str:
|
def get_implementation(self) -> str:
|
||||||
context = {
|
context = {
|
||||||
"cpuif": self,
|
"cpuif": self,
|
||||||
"cpuif_reset": self.cpuif_reset,
|
|
||||||
"data_width": self.data_width,
|
|
||||||
"addr_width": self.addr_width,
|
|
||||||
"get_always_ff_event": get_always_ff_event,
|
"get_always_ff_event": get_always_ff_event,
|
||||||
|
"clog2": clog2,
|
||||||
}
|
}
|
||||||
|
|
||||||
template = self.exp.jj_env.get_template(self.template_path)
|
template = self.exp.jj_env.get_template(self.template_path)
|
||||||
|
|||||||
@@ -3,17 +3,19 @@ from typing import Union
|
|||||||
|
|
||||||
import jinja2 as jj
|
import jinja2 as jj
|
||||||
from systemrdl.node import AddrmapNode, RootNode
|
from systemrdl.node import AddrmapNode, RootNode
|
||||||
|
from systemrdl.walker import RDLWalker
|
||||||
|
|
||||||
from .addr_decode import AddressDecode
|
from .addr_decode import AddressDecode
|
||||||
from .field_logic import FieldLogic
|
from .field_logic import FieldLogic
|
||||||
from .dereferencer import Dereferencer
|
from .dereferencer import Dereferencer
|
||||||
from .readback import Readback
|
from .readback import Readback
|
||||||
from .signals import InferredSignal, SignalBase
|
from .signals import InferredSignal, RDLSignal
|
||||||
|
|
||||||
from .cpuif import CpuifBase
|
from .cpuif import CpuifBase
|
||||||
from .cpuif.apb3 import APB3_Cpuif
|
from .cpuif.apb3 import APB3_Cpuif
|
||||||
from .hwif import Hwif
|
from .hwif import Hwif
|
||||||
from .utils import get_always_ff_event
|
from .utils import get_always_ff_event
|
||||||
|
from .scan_design import DesignScanner
|
||||||
|
|
||||||
class RegblockExporter:
|
class RegblockExporter:
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@@ -29,10 +31,9 @@ class RegblockExporter:
|
|||||||
self.cpuif = None # type: CpuifBase
|
self.cpuif = None # type: CpuifBase
|
||||||
self.address_decode = AddressDecode(self)
|
self.address_decode = AddressDecode(self)
|
||||||
self.field_logic = FieldLogic(self)
|
self.field_logic = FieldLogic(self)
|
||||||
self.readback = Readback(self)
|
self.readback = None # type: Readback
|
||||||
self.dereferencer = Dereferencer(self)
|
self.dereferencer = Dereferencer(self)
|
||||||
self.default_resetsignal = InferredSignal("rst")
|
self.default_resetsignal = InferredSignal("rst")
|
||||||
self.cpuif_reset = self.default_resetsignal
|
|
||||||
|
|
||||||
|
|
||||||
if user_template_dir:
|
if user_template_dir:
|
||||||
@@ -67,41 +68,55 @@ class RegblockExporter:
|
|||||||
|
|
||||||
|
|
||||||
cpuif_cls = kwargs.pop("cpuif_cls", APB3_Cpuif)
|
cpuif_cls = kwargs.pop("cpuif_cls", APB3_Cpuif)
|
||||||
hwif_cls = kwargs.pop("hwif_cls", Hwif)
|
|
||||||
module_name = kwargs.pop("module_name", self.top_node.inst_name)
|
module_name = kwargs.pop("module_name", self.top_node.inst_name)
|
||||||
package_name = kwargs.pop("package_name", module_name + "_pkg")
|
package_name = kwargs.pop("package_name", module_name + "_pkg")
|
||||||
module_file_path = os.path.join(output_dir, module_name + ".sv")
|
|
||||||
package_file_path = os.path.join(output_dir, package_name + ".sv")
|
# Pipelining options
|
||||||
|
retime_read_response = kwargs.pop("retime_read_response", True)
|
||||||
|
retime_read_fanin = kwargs.pop("retime_read_fanin", False)
|
||||||
|
|
||||||
# Check for stray kwargs
|
# Check for stray kwargs
|
||||||
if kwargs:
|
if kwargs:
|
||||||
raise TypeError("got an unexpected keyword argument '%s'" % list(kwargs.keys())[0])
|
raise TypeError("got an unexpected keyword argument '%s'" % list(kwargs.keys())[0])
|
||||||
|
|
||||||
|
|
||||||
|
# Scan the design for any unsupported features
|
||||||
|
# Also collect pre-export information
|
||||||
|
scanner = DesignScanner(self)
|
||||||
|
RDLWalker().walk(self.top_node, scanner)
|
||||||
|
if scanner.msg.had_error:
|
||||||
|
scanner.msg.fatal(
|
||||||
|
"Unable to export due to previous errors"
|
||||||
|
)
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
# TODO: Scan design...
|
cpuif_reset_tmp = self.top_node.cpuif_reset
|
||||||
|
if cpuif_reset_tmp:
|
||||||
# TODO: derive this from somewhere
|
cpuif_reset = RDLSignal(cpuif_reset_tmp)
|
||||||
self.cpuif_reset = self.default_resetsignal
|
else:
|
||||||
reset_signals = set([self.cpuif_reset, self.default_resetsignal])
|
cpuif_reset = self.default_resetsignal
|
||||||
|
reset_signals = set([cpuif_reset, self.default_resetsignal])
|
||||||
|
|
||||||
self.cpuif = cpuif_cls(
|
self.cpuif = cpuif_cls(
|
||||||
self,
|
self,
|
||||||
cpuif_reset=self.cpuif_reset, # TODO:
|
cpuif_reset=cpuif_reset,
|
||||||
data_width=32, # TODO: derive from the regwidth used by regs
|
data_width=scanner.cpuif_data_width,
|
||||||
addr_width=32 # TODO:
|
addr_width=self.top_node.size.bit_length()
|
||||||
)
|
)
|
||||||
|
|
||||||
self.hwif = hwif_cls(
|
self.hwif = Hwif(
|
||||||
self,
|
self,
|
||||||
package_name=package_name,
|
package_name=package_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.readback = Readback(
|
||||||
|
self,
|
||||||
|
retime_read_fanin
|
||||||
|
)
|
||||||
|
|
||||||
# Build Jinja template context
|
# Build Jinja template context
|
||||||
context = {
|
context = {
|
||||||
"module_name": module_name,
|
"module_name": module_name,
|
||||||
"data_width": 32, # TODO:
|
|
||||||
"addr_width": 32, # TODO:
|
|
||||||
"reset_signals": reset_signals,
|
"reset_signals": reset_signals,
|
||||||
"user_signals": [], # TODO:
|
"user_signals": [], # TODO:
|
||||||
"interrupts": [], # TODO:
|
"interrupts": [], # TODO:
|
||||||
@@ -110,13 +125,17 @@ class RegblockExporter:
|
|||||||
"address_decode": self.address_decode,
|
"address_decode": self.address_decode,
|
||||||
"field_logic": self.field_logic,
|
"field_logic": self.field_logic,
|
||||||
"readback": self.readback,
|
"readback": self.readback,
|
||||||
|
"get_always_ff_event": get_always_ff_event,
|
||||||
|
"retime_read_response": retime_read_response,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Write out design
|
# Write out design
|
||||||
|
package_file_path = os.path.join(output_dir, package_name + ".sv")
|
||||||
template = self.jj_env.get_template("package_tmpl.sv")
|
template = self.jj_env.get_template("package_tmpl.sv")
|
||||||
stream = template.stream(context)
|
stream = template.stream(context)
|
||||||
stream.dump(package_file_path)
|
stream.dump(package_file_path)
|
||||||
|
|
||||||
|
module_file_path = os.path.join(output_dir, module_name + ".sv")
|
||||||
template = self.jj_env.get_template("module_tmpl.sv")
|
template = self.jj_env.get_template("module_tmpl.sv")
|
||||||
stream = template.stream(context)
|
stream = template.stream(context)
|
||||||
stream.dump(module_file_path)
|
stream.dump(module_file_path)
|
||||||
|
|||||||
@@ -19,20 +19,17 @@ module {{module_name}} (
|
|||||||
{{hwif.port_declaration|indent(8)}}
|
{{hwif.port_declaration|indent(8)}}
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam ADDR_WIDTH = {{addr_width}};
|
|
||||||
localparam DATA_WIDTH = {{data_width}};
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// CPU Bus interface logic
|
// CPU Bus interface logic
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
logic cpuif_req;
|
logic cpuif_req;
|
||||||
logic cpuif_req_is_wr;
|
logic cpuif_req_is_wr;
|
||||||
logic [ADDR_WIDTH-1:0] cpuif_addr;
|
logic [{{cpuif.addr_width-1}}:0] cpuif_addr;
|
||||||
logic [DATA_WIDTH-1:0] cpuif_wr_data;
|
logic [{{cpuif.data_width-1}}:0] cpuif_wr_data;
|
||||||
logic [DATA_WIDTH-1:0] cpuif_wr_bitstrb;
|
logic [{{cpuif.data_width-1}}:0] cpuif_wr_biten;
|
||||||
|
|
||||||
logic cpuif_rd_ack;
|
logic cpuif_rd_ack;
|
||||||
logic [DATA_WIDTH-1:0] cpuif_rd_data;
|
logic [{{cpuif.data_width-1}}:0] cpuif_rd_data;
|
||||||
logic cpuif_rd_err;
|
logic cpuif_rd_err;
|
||||||
|
|
||||||
logic cpuif_wr_ack;
|
logic cpuif_wr_ack;
|
||||||
@@ -47,8 +44,8 @@ module {{module_name}} (
|
|||||||
decoded_reg_strb_t decoded_reg_strb;
|
decoded_reg_strb_t decoded_reg_strb;
|
||||||
logic decoded_req;
|
logic decoded_req;
|
||||||
logic decoded_req_is_wr;
|
logic decoded_req_is_wr;
|
||||||
logic [DATA_WIDTH-1:0] decoded_wr_data;
|
logic [{{cpuif.data_width-1}}:0] decoded_wr_data;
|
||||||
logic [DATA_WIDTH-1:0] decoded_wr_bitstrb;
|
logic [{{cpuif.data_width-1}}:0] decoded_wr_biten;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
{{address_decode.get_implementation()|indent(8)}}
|
{{address_decode.get_implementation()|indent(8)}}
|
||||||
@@ -62,7 +59,7 @@ module {{module_name}} (
|
|||||||
assign decoded_req = cpuif_req;
|
assign decoded_req = cpuif_req;
|
||||||
assign decoded_req_is_wr = cpuif_req_is_wr;
|
assign decoded_req_is_wr = cpuif_req_is_wr;
|
||||||
assign decoded_wr_data = cpuif_wr_data;
|
assign decoded_wr_data = cpuif_wr_data;
|
||||||
assign decoded_wr_bitstrb = cpuif_wr_bitstrb;
|
assign decoded_wr_biten = cpuif_wr_biten;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Field logic
|
// Field logic
|
||||||
@@ -76,6 +73,27 @@ module {{module_name}} (
|
|||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Readback
|
// Readback
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
logic readback_err;
|
||||||
|
logic readback_done;
|
||||||
|
logic [{{cpuif.data_width-1}}:0] readback_data;
|
||||||
{{readback.get_implementation()|indent}}
|
{{readback.get_implementation()|indent}}
|
||||||
|
|
||||||
|
{% if retime_read_response %}
|
||||||
|
always_ff {{get_always_ff_event(cpuif.reset)}} begin
|
||||||
|
if({{cpuif.reset.activehigh_identifier}}) begin
|
||||||
|
cpuif_rd_ack <= '0;
|
||||||
|
cpuif_rd_data <= '0;
|
||||||
|
cpuif_rd_err <= '0;
|
||||||
|
end else begin
|
||||||
|
cpuif_rd_ack <= readback_done;
|
||||||
|
cpuif_rd_data <= readback_data;
|
||||||
|
cpuif_rd_err <= readback_err;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% else %}
|
||||||
|
assign cpuif_rd_ack = readback_done;
|
||||||
|
assign cpuif_rd_data = readback_data;
|
||||||
|
assign cpuif_rd_err = readback_err;
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
import math
|
||||||
|
|
||||||
from .generators import ReadbackAssignmentGenerator
|
from .generators import ReadbackAssignmentGenerator
|
||||||
from ..utils import get_always_ff_event
|
from ..utils import get_always_ff_event
|
||||||
@@ -8,8 +9,9 @@ if TYPE_CHECKING:
|
|||||||
from systemrdl.node import AddrmapNode
|
from systemrdl.node import AddrmapNode
|
||||||
|
|
||||||
class Readback:
|
class Readback:
|
||||||
def __init__(self, exp:'RegblockExporter'):
|
def __init__(self, exp:'RegblockExporter', do_fanin_stage: bool):
|
||||||
self.exp = exp
|
self.exp = exp
|
||||||
|
self.do_fanin_stage = do_fanin_stage
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def top_node(self) -> 'AddrmapNode':
|
def top_node(self) -> 'AddrmapNode':
|
||||||
@@ -18,13 +20,49 @@ class Readback:
|
|||||||
def get_implementation(self) -> str:
|
def get_implementation(self) -> str:
|
||||||
gen = ReadbackAssignmentGenerator(self.exp)
|
gen = ReadbackAssignmentGenerator(self.exp)
|
||||||
array_assignments = gen.get_content(self.top_node)
|
array_assignments = gen.get_content(self.top_node)
|
||||||
|
array_size = gen.current_offset
|
||||||
|
|
||||||
|
# Enabling the fanin stage doesnt make sense if readback fanin is
|
||||||
|
# small. This also avoids pesky corner cases
|
||||||
|
if array_size < 4:
|
||||||
|
self.do_fanin_stage = False
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"array_assignments" : array_assignments,
|
"array_assignments" : array_assignments,
|
||||||
"array_size" : gen.current_offset,
|
"array_size" : array_size,
|
||||||
"get_always_ff_event": get_always_ff_event,
|
"get_always_ff_event": get_always_ff_event,
|
||||||
"cpuif_reset": self.exp.cpuif_reset,
|
"cpuif": self.exp.cpuif,
|
||||||
|
"do_fanin_stage": self.do_fanin_stage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.do_fanin_stage:
|
||||||
|
# If adding a fanin pipeline stage, goal is to try to
|
||||||
|
# split the fanin path in the middle so that fanin into the stage
|
||||||
|
# and the following are roughly balanced.
|
||||||
|
fanin_target = math.sqrt(array_size)
|
||||||
|
|
||||||
|
# Size of fanin group to consume per fanin element
|
||||||
|
fanin_stride = math.floor(fanin_target)
|
||||||
|
|
||||||
|
# Number of array elements to reduce to.
|
||||||
|
# Round up to an extra element in case there is some residual
|
||||||
|
fanin_array_size = math.ceil(array_size / fanin_stride)
|
||||||
|
|
||||||
|
# leftovers are handled in an extra array element
|
||||||
|
fanin_residual_stride = array_size % fanin_stride
|
||||||
|
|
||||||
|
if fanin_residual_stride != 0:
|
||||||
|
# If there is a partial fanin element, reduce the number of
|
||||||
|
# loops performed in the bulk fanin stage
|
||||||
|
fanin_loop_iter = fanin_array_size - 1
|
||||||
|
else:
|
||||||
|
fanin_loop_iter = fanin_array_size
|
||||||
|
|
||||||
|
context['fanin_stride'] = fanin_stride
|
||||||
|
context['fanin_array_size'] = fanin_array_size
|
||||||
|
context['fanin_residual_stride'] = fanin_residual_stride
|
||||||
|
context['fanin_loop_iter'] = fanin_loop_iter
|
||||||
|
|
||||||
template = self.exp.jj_env.get_template(
|
template = self.exp.jj_env.get_template(
|
||||||
"readback/templates/readback.sv"
|
"readback/templates/readback.sv"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,45 +1,68 @@
|
|||||||
{% if array_assignments is not none %}
|
{% if array_assignments is not none %}
|
||||||
logic readback_err;
|
// Assign readback values to a flattened array
|
||||||
logic readback_done;
|
logic [{{cpuif.data_width-1}}:0] readback_array[{{array_size}}];
|
||||||
logic [DATA_WIDTH-1:0] readback_data;
|
|
||||||
logic [DATA_WIDTH-1:0] readback_array[{{array_size}}];
|
|
||||||
|
|
||||||
{{array_assignments}}
|
{{array_assignments}}
|
||||||
|
|
||||||
|
{% if do_fanin_stage %}
|
||||||
|
// fanin stage
|
||||||
|
logic [31:0] readback_array_c[{{fanin_array_size}}];
|
||||||
|
for(genvar g=0; g<{{fanin_loop_iter}}; g++) begin
|
||||||
|
always_comb begin
|
||||||
|
automatic logic [31:0] readback_data_var;
|
||||||
|
readback_data_var = '0;
|
||||||
|
for(int i=g*{{fanin_stride}}; i<((g+1)*{{fanin_stride}}); i++) readback_data_var |= readback_array[i];
|
||||||
|
readback_array_c[g] = readback_data_var;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{%- if fanin_residual_stride == 1 %}
|
||||||
|
assign readback_array_c[{{fanin_array_size-1}}] = readback_array[{{array_size-1}}];
|
||||||
|
{%- elif fanin_residual_stride > 1 %}
|
||||||
always_comb begin
|
always_comb begin
|
||||||
automatic logic [DATA_WIDTH-1:0] readback_data_var;
|
automatic logic [31:0] readback_data_var;
|
||||||
|
readback_data_var = '0;
|
||||||
|
for(int i={{(fanin_array_size-1) * fanin_stride}}; i<{{array_size-1}}; i++) readback_data_var |= readback_array[i];
|
||||||
|
readback_array_c[{{fanin_array_size-1}}] = readback_data_var;
|
||||||
|
end
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
logic [31:0] readback_array_r[{{fanin_array_size}}];
|
||||||
|
logic readback_done_r;
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if(rst) begin
|
||||||
|
for(int i=0; i<{{fanin_array_size}}; i++) readback_array_r[i] <= '0;
|
||||||
|
readback_done_r <= '0;
|
||||||
|
end else begin
|
||||||
|
readback_array_r <= readback_array_c;
|
||||||
|
readback_done_r <= decoded_req & ~decoded_req_is_wr;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Reduce the array
|
||||||
|
always_comb begin
|
||||||
|
automatic logic [31:0] readback_data_var;
|
||||||
readback_done = decoded_req & ~decoded_req_is_wr;
|
readback_done = decoded_req & ~decoded_req_is_wr;
|
||||||
readback_err = '0;
|
readback_err = '0;
|
||||||
|
|
||||||
readback_data_var = '0;
|
readback_data_var = '0;
|
||||||
for(int i=0; i<{{array_size}}; i++) begin
|
for(int i=0; i<{{fanin_array_size}}; i++) readback_data_var |= readback_array_r[i];
|
||||||
readback_data_var |= readback_array[i];
|
|
||||||
end
|
|
||||||
readback_data = readback_data_var;
|
readback_data = readback_data_var;
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff {{get_always_ff_event(cpuif_reset)}} begin
|
{%- else %}
|
||||||
if({{cpuif_reset.activehigh_identifier}}) begin
|
// Reduce the array
|
||||||
cpuif_rd_ack <= '0;
|
always_comb begin
|
||||||
cpuif_rd_data <= '0;
|
automatic logic [{{cpuif.data_width-1}}:0] readback_data_var;
|
||||||
cpuif_rd_err <= '0;
|
readback_done = decoded_req & ~decoded_req_is_wr;
|
||||||
end else begin
|
readback_err = '0;
|
||||||
cpuif_rd_ack <= readback_done;
|
readback_data_var = '0;
|
||||||
cpuif_rd_data <= readback_data;
|
for(int i=0; i<{{array_size}}; i++) readback_data_var |= readback_array[i];
|
||||||
cpuif_rd_err <= readback_err;
|
readback_data = readback_data_var;
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{%- else %}
|
{%- else %}
|
||||||
always_ff {{get_always_ff_event(cpuif_reset)}} begin
|
assign readback_done = decoded_req & ~decoded_req_is_wr;
|
||||||
if({{cpuif_reset.activehigh_identifier}}) begin
|
assign readback_data = '0;
|
||||||
cpuif_rd_ack <= '0;
|
assign readback_err = '0;
|
||||||
end else begin
|
|
||||||
cpuif_rd_ack <= decoded_req & ~decoded_req_is_wr;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign cpuif_rd_data = '0;
|
|
||||||
assign cpuif_rd_err = '0;
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,14 +1,53 @@
|
|||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
"""
|
from systemrdl.walker import RDLListener
|
||||||
- Signal References
|
from systemrdl.node import AddrmapNode
|
||||||
Collect any references to signals that lie outside of the hierarchy
|
|
||||||
These will be added as top-level signals
|
if TYPE_CHECKING:
|
||||||
- top-level interrupts
|
from systemrdl.node import Node, RegNode, SignalNode, MemNode
|
||||||
|
from .exporter import RegblockExporter
|
||||||
|
|
||||||
|
|
||||||
Validate:
|
class DesignScanner(RDLListener):
|
||||||
- Error if a property references a non-signal component, or property reference from
|
"""
|
||||||
outside the export hierarchy
|
Scans through the register model and validates that any unsupported features
|
||||||
- No Mem components allowed
|
are not present.
|
||||||
- Uniform regwidth, accesswidth, etc.
|
|
||||||
"""
|
Also collects any information that is required prior to the start of the export process.
|
||||||
|
"""
|
||||||
|
def __init__(self, exp:'RegblockExporter'):
|
||||||
|
self.exp = exp
|
||||||
|
self.cpuif_data_width = 0
|
||||||
|
self.msg = exp.top_node.env.msg
|
||||||
|
|
||||||
|
def enter_Reg(self, node: 'RegNode') -> None:
|
||||||
|
# The CPUIF's bus width is sized according to the largest register in the design
|
||||||
|
self.cpuif_data_width = max(self.cpuif_data_width, node.get_property("regwidth"))
|
||||||
|
|
||||||
|
# TODO: Collect any references to signals that lie outside of the hierarchy
|
||||||
|
# These will be added as top-level signals
|
||||||
|
|
||||||
|
def enter_Component(self, node: 'Node') -> None:
|
||||||
|
if not isinstance(node, AddrmapNode) and node.external:
|
||||||
|
self.msg.error(
|
||||||
|
"Exporter does not support external components",
|
||||||
|
node.inst.inst_src_ref
|
||||||
|
)
|
||||||
|
|
||||||
|
def enter_Signal(self, node: 'SignalNode') -> None:
|
||||||
|
# If encountering a CPUIF reset that is nested within the register model,
|
||||||
|
# warn that it will be ignored.
|
||||||
|
# Only cpuif resets in the top-level node or above will be honored
|
||||||
|
if node.get_property('cpuif_reset') and (node.parent != self.exp.top_node):
|
||||||
|
self.msg.warning(
|
||||||
|
"Only cpuif_reset signals that are instantiated in the top-level "
|
||||||
|
+ "addrmap or above will be honored. Any cpuif_reset signals nested "
|
||||||
|
+ "within children of the addrmap being exported will be ignored.",
|
||||||
|
node.inst.inst_src_ref
|
||||||
|
)
|
||||||
|
|
||||||
|
def enter_Mem(self, node: 'MemNode') -> None:
|
||||||
|
self.msg.error(
|
||||||
|
"Cannot export a register block that contains a memory",
|
||||||
|
node.inst.inst_src_ref
|
||||||
|
)
|
||||||
|
|||||||
@@ -30,3 +30,6 @@ def get_always_ff_event(resetsignal: 'Optional[SignalBase]') -> str:
|
|||||||
elif resetsignal.is_async and not resetsignal.is_activehigh:
|
elif resetsignal.is_async and not resetsignal.is_activehigh:
|
||||||
return f"@(posedge clk or negedge {resetsignal.identifier})"
|
return f"@(posedge clk or negedge {resetsignal.identifier})"
|
||||||
return "@(posedge clk)"
|
return "@(posedge clk)"
|
||||||
|
|
||||||
|
def clog2(n: int) -> int:
|
||||||
|
return n.bit_length() - 1
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
|
||||||
../export.py test_regblock.rdl
|
../export.py test_regblock.rdl
|
||||||
|
|
||||||
vlog -sv -suppress 2720 -quiet -f src.f
|
vlog -sv -f vlog_args.f -f src.f
|
||||||
vsim -c -quiet tb -do "log -r /*; run -all; exit;"
|
vsim -c -quiet tb -do "log -r /*; run -all; exit;"
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
addrmap test_regblock {
|
addrmap test_regblock {
|
||||||
reg my_reg {
|
reg my_reg {
|
||||||
field { sw=rw; hw=r; anded;} a[8] = 0x10;
|
field { sw=rw; hw=r; anded;} a[8] = 0x10;
|
||||||
field { sw=rw; hw=r; ored;} b[8] = 0x20;
|
//field { sw=rw; hw=r; ored;} b[8] = 0x20;
|
||||||
field { sw=rw; hw=r; swmod;} c[8] = 0x30;
|
//field { sw=rw; hw=r; swmod;} c[8] = 0x30;
|
||||||
};
|
};
|
||||||
|
|
||||||
my_reg r0 @0x000;
|
//my_reg r0 @0x000;
|
||||||
my_reg r1 @0x100;
|
//my_reg r1 @0x100;
|
||||||
my_reg r2 @0x200;
|
my_reg r2[112] @0x200 += 8;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,20 +8,17 @@ module test_regblock (
|
|||||||
output test_regblock_pkg::test_regblock__out_t hwif_out
|
output test_regblock_pkg::test_regblock__out_t hwif_out
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam ADDR_WIDTH = 32;
|
|
||||||
localparam DATA_WIDTH = 32;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// CPU Bus interface logic
|
// CPU Bus interface logic
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
logic cpuif_req;
|
logic cpuif_req;
|
||||||
logic cpuif_req_is_wr;
|
logic cpuif_req_is_wr;
|
||||||
logic [ADDR_WIDTH-1:0] cpuif_addr;
|
logic [10:0] cpuif_addr;
|
||||||
logic [DATA_WIDTH-1:0] cpuif_wr_data;
|
logic [31:0] cpuif_wr_data;
|
||||||
logic [DATA_WIDTH-1:0] cpuif_wr_bitstrb;
|
logic [31:0] cpuif_wr_biten;
|
||||||
|
|
||||||
logic cpuif_rd_ack;
|
logic cpuif_rd_ack;
|
||||||
logic [DATA_WIDTH-1:0] cpuif_rd_data;
|
logic [31:0] cpuif_rd_data;
|
||||||
logic cpuif_rd_err;
|
logic cpuif_rd_err;
|
||||||
|
|
||||||
logic cpuif_wr_ack;
|
logic cpuif_wr_ack;
|
||||||
@@ -43,7 +40,7 @@ module test_regblock (
|
|||||||
is_active <= '1;
|
is_active <= '1;
|
||||||
cpuif_req <= '1;
|
cpuif_req <= '1;
|
||||||
cpuif_req_is_wr <= s_apb.PWRITE;
|
cpuif_req_is_wr <= s_apb.PWRITE;
|
||||||
cpuif_addr <= s_apb.PADDR[ADDR_WIDTH-1:0];
|
cpuif_addr <= {s_apb.PADDR[10:2], 2'b0};
|
||||||
cpuif_wr_data <= s_apb.PWDATA;
|
cpuif_wr_data <= s_apb.PWDATA;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
@@ -54,7 +51,7 @@ module test_regblock (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assign cpuif_wr_bitstrb = '0;
|
assign cpuif_wr_biten = '1;
|
||||||
|
|
||||||
// Response
|
// Response
|
||||||
assign s_apb.PREADY = cpuif_rd_ack | cpuif_wr_ack;
|
assign s_apb.PREADY = cpuif_rd_ack | cpuif_wr_ack;
|
||||||
@@ -66,20 +63,18 @@ module test_regblock (
|
|||||||
// Address Decode
|
// Address Decode
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
logic r0;
|
logic r2[112];
|
||||||
logic r1;
|
|
||||||
logic r2;
|
|
||||||
} decoded_reg_strb_t;
|
} decoded_reg_strb_t;
|
||||||
decoded_reg_strb_t decoded_reg_strb;
|
decoded_reg_strb_t decoded_reg_strb;
|
||||||
logic decoded_req;
|
logic decoded_req;
|
||||||
logic decoded_req_is_wr;
|
logic decoded_req_is_wr;
|
||||||
logic [DATA_WIDTH-1:0] decoded_wr_data;
|
logic [31:0] decoded_wr_data;
|
||||||
logic [DATA_WIDTH-1:0] decoded_wr_bitstrb;
|
logic [31:0] decoded_wr_biten;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
decoded_reg_strb.r0 = cpuif_req & (cpuif_addr == 'h0);
|
for(int i0=0; i0<112; i0++) begin
|
||||||
decoded_reg_strb.r1 = cpuif_req & (cpuif_addr == 'h100);
|
decoded_reg_strb.r2[i0] = cpuif_req & (cpuif_addr == 'h200 + i0*'h8);
|
||||||
decoded_reg_strb.r2 = cpuif_req & (cpuif_addr == 'h200);
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// Writes are always granted with no error response
|
// Writes are always granted with no error response
|
||||||
@@ -90,7 +85,7 @@ module test_regblock (
|
|||||||
assign decoded_req = cpuif_req;
|
assign decoded_req = cpuif_req;
|
||||||
assign decoded_req_is_wr = cpuif_req_is_wr;
|
assign decoded_req_is_wr = cpuif_req_is_wr;
|
||||||
assign decoded_wr_data = cpuif_wr_data;
|
assign decoded_wr_data = cpuif_wr_data;
|
||||||
assign decoded_wr_bitstrb = cpuif_wr_bitstrb;
|
assign decoded_wr_biten = cpuif_wr_biten;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Field logic
|
// Field logic
|
||||||
@@ -101,262 +96,64 @@ module test_regblock (
|
|||||||
logic [7:0] next;
|
logic [7:0] next;
|
||||||
logic load_next;
|
logic load_next;
|
||||||
} a;
|
} a;
|
||||||
struct {
|
} r2[112];
|
||||||
logic [7:0] next;
|
|
||||||
logic load_next;
|
|
||||||
} b;
|
|
||||||
struct {
|
|
||||||
logic [7:0] next;
|
|
||||||
logic load_next;
|
|
||||||
} c;
|
|
||||||
} r0;
|
|
||||||
struct {
|
|
||||||
struct {
|
|
||||||
logic [7:0] next;
|
|
||||||
logic load_next;
|
|
||||||
} a;
|
|
||||||
struct {
|
|
||||||
logic [7:0] next;
|
|
||||||
logic load_next;
|
|
||||||
} b;
|
|
||||||
struct {
|
|
||||||
logic [7:0] next;
|
|
||||||
logic load_next;
|
|
||||||
} c;
|
|
||||||
} r1;
|
|
||||||
struct {
|
|
||||||
struct {
|
|
||||||
logic [7:0] next;
|
|
||||||
logic load_next;
|
|
||||||
} a;
|
|
||||||
struct {
|
|
||||||
logic [7:0] next;
|
|
||||||
logic load_next;
|
|
||||||
} b;
|
|
||||||
struct {
|
|
||||||
logic [7:0] next;
|
|
||||||
logic load_next;
|
|
||||||
} c;
|
|
||||||
} r2;
|
|
||||||
} field_combo_t;
|
} field_combo_t;
|
||||||
field_combo_t field_combo;
|
field_combo_t field_combo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct {
|
struct {
|
||||||
logic [7:0] a;
|
logic [7:0] a;
|
||||||
logic [7:0] b;
|
} r2[112];
|
||||||
logic [7:0] c;
|
|
||||||
} r0;
|
|
||||||
struct {
|
|
||||||
logic [7:0] a;
|
|
||||||
logic [7:0] b;
|
|
||||||
logic [7:0] c;
|
|
||||||
} r1;
|
|
||||||
struct {
|
|
||||||
logic [7:0] a;
|
|
||||||
logic [7:0] b;
|
|
||||||
logic [7:0] c;
|
|
||||||
} r2;
|
|
||||||
} field_storage_t;
|
} field_storage_t;
|
||||||
field_storage_t field_storage;
|
field_storage_t field_storage;
|
||||||
|
|
||||||
// Field: test_regblock.r0.a
|
for(genvar i0=0; i0<112; i0++) begin
|
||||||
always_comb begin
|
// Field: test_regblock.r2[].a
|
||||||
field_combo.r0.a.next = field_storage.r0.a;
|
always_comb begin
|
||||||
field_combo.r0.a.load_next = '0;
|
field_combo.r2[i0].a.next = field_storage.r2[i0].a;
|
||||||
if(decoded_reg_strb.r0 && decoded_req_is_wr) begin // SW write
|
field_combo.r2[i0].a.load_next = '0;
|
||||||
field_combo.r0.a.next = decoded_wr_data[7:0];
|
if(decoded_reg_strb.r2[i0] && decoded_req_is_wr) begin // SW write
|
||||||
field_combo.r0.a.load_next = '1;
|
field_combo.r2[i0].a.next = decoded_wr_data[7:0];
|
||||||
|
field_combo.r2[i0].a.load_next = '1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
always_ff @(posedge clk) begin
|
||||||
always_ff @(posedge clk) begin
|
if(rst) begin
|
||||||
if(rst) begin
|
field_storage.r2[i0].a <= 'h10;
|
||||||
field_storage.r0.a <= 'h10;
|
end else if(field_combo.r2[i0].a.load_next) begin
|
||||||
end else if(field_combo.r0.a.load_next) begin
|
field_storage.r2[i0].a <= field_combo.r2[i0].a.next;
|
||||||
field_storage.r0.a <= field_combo.r0.a.next;
|
end
|
||||||
end
|
end
|
||||||
|
assign hwif_out.r2[i0].a.value = field_storage.r2[i0].a;
|
||||||
|
assign hwif_out.r2[i0].a.anded = &(field_storage.r2[i0].a);
|
||||||
end
|
end
|
||||||
assign hwif_out.r0.a.value = field_storage.r0.a;
|
|
||||||
assign hwif_out.r0.a.anded = &(field_storage.r0.a);
|
|
||||||
// Field: test_regblock.r0.b
|
|
||||||
always_comb begin
|
|
||||||
field_combo.r0.b.next = field_storage.r0.b;
|
|
||||||
field_combo.r0.b.load_next = '0;
|
|
||||||
if(decoded_reg_strb.r0 && decoded_req_is_wr) begin // SW write
|
|
||||||
field_combo.r0.b.next = decoded_wr_data[15:8];
|
|
||||||
field_combo.r0.b.load_next = '1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
field_storage.r0.b <= 'h20;
|
|
||||||
end else if(field_combo.r0.b.load_next) begin
|
|
||||||
field_storage.r0.b <= field_combo.r0.b.next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign hwif_out.r0.b.value = field_storage.r0.b;
|
|
||||||
assign hwif_out.r0.b.ored = |(field_storage.r0.b);
|
|
||||||
// Field: test_regblock.r0.c
|
|
||||||
always_comb begin
|
|
||||||
field_combo.r0.c.next = field_storage.r0.c;
|
|
||||||
field_combo.r0.c.load_next = '0;
|
|
||||||
if(decoded_reg_strb.r0 && decoded_req_is_wr) begin // SW write
|
|
||||||
field_combo.r0.c.next = decoded_wr_data[23:16];
|
|
||||||
field_combo.r0.c.load_next = '1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
field_storage.r0.c <= 'h30;
|
|
||||||
end else if(field_combo.r0.c.load_next) begin
|
|
||||||
field_storage.r0.c <= field_combo.r0.c.next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign hwif_out.r0.c.value = field_storage.r0.c;
|
|
||||||
assign hwif_out.r0.c.swmod = decoded_reg_strb.r0 && decoded_req_is_wr;
|
|
||||||
// Field: test_regblock.r1.a
|
|
||||||
always_comb begin
|
|
||||||
field_combo.r1.a.next = field_storage.r1.a;
|
|
||||||
field_combo.r1.a.load_next = '0;
|
|
||||||
if(decoded_reg_strb.r1 && decoded_req_is_wr) begin // SW write
|
|
||||||
field_combo.r1.a.next = decoded_wr_data[7:0];
|
|
||||||
field_combo.r1.a.load_next = '1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
field_storage.r1.a <= 'h10;
|
|
||||||
end else if(field_combo.r1.a.load_next) begin
|
|
||||||
field_storage.r1.a <= field_combo.r1.a.next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign hwif_out.r1.a.value = field_storage.r1.a;
|
|
||||||
assign hwif_out.r1.a.anded = &(field_storage.r1.a);
|
|
||||||
// Field: test_regblock.r1.b
|
|
||||||
always_comb begin
|
|
||||||
field_combo.r1.b.next = field_storage.r1.b;
|
|
||||||
field_combo.r1.b.load_next = '0;
|
|
||||||
if(decoded_reg_strb.r1 && decoded_req_is_wr) begin // SW write
|
|
||||||
field_combo.r1.b.next = decoded_wr_data[15:8];
|
|
||||||
field_combo.r1.b.load_next = '1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
field_storage.r1.b <= 'h20;
|
|
||||||
end else if(field_combo.r1.b.load_next) begin
|
|
||||||
field_storage.r1.b <= field_combo.r1.b.next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign hwif_out.r1.b.value = field_storage.r1.b;
|
|
||||||
assign hwif_out.r1.b.ored = |(field_storage.r1.b);
|
|
||||||
// Field: test_regblock.r1.c
|
|
||||||
always_comb begin
|
|
||||||
field_combo.r1.c.next = field_storage.r1.c;
|
|
||||||
field_combo.r1.c.load_next = '0;
|
|
||||||
if(decoded_reg_strb.r1 && decoded_req_is_wr) begin // SW write
|
|
||||||
field_combo.r1.c.next = decoded_wr_data[23:16];
|
|
||||||
field_combo.r1.c.load_next = '1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
field_storage.r1.c <= 'h30;
|
|
||||||
end else if(field_combo.r1.c.load_next) begin
|
|
||||||
field_storage.r1.c <= field_combo.r1.c.next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign hwif_out.r1.c.value = field_storage.r1.c;
|
|
||||||
assign hwif_out.r1.c.swmod = decoded_reg_strb.r1 && decoded_req_is_wr;
|
|
||||||
// Field: test_regblock.r2.a
|
|
||||||
always_comb begin
|
|
||||||
field_combo.r2.a.next = field_storage.r2.a;
|
|
||||||
field_combo.r2.a.load_next = '0;
|
|
||||||
if(decoded_reg_strb.r2 && decoded_req_is_wr) begin // SW write
|
|
||||||
field_combo.r2.a.next = decoded_wr_data[7:0];
|
|
||||||
field_combo.r2.a.load_next = '1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
field_storage.r2.a <= 'h10;
|
|
||||||
end else if(field_combo.r2.a.load_next) begin
|
|
||||||
field_storage.r2.a <= field_combo.r2.a.next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign hwif_out.r2.a.value = field_storage.r2.a;
|
|
||||||
assign hwif_out.r2.a.anded = &(field_storage.r2.a);
|
|
||||||
// Field: test_regblock.r2.b
|
|
||||||
always_comb begin
|
|
||||||
field_combo.r2.b.next = field_storage.r2.b;
|
|
||||||
field_combo.r2.b.load_next = '0;
|
|
||||||
if(decoded_reg_strb.r2 && decoded_req_is_wr) begin // SW write
|
|
||||||
field_combo.r2.b.next = decoded_wr_data[15:8];
|
|
||||||
field_combo.r2.b.load_next = '1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
field_storage.r2.b <= 'h20;
|
|
||||||
end else if(field_combo.r2.b.load_next) begin
|
|
||||||
field_storage.r2.b <= field_combo.r2.b.next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign hwif_out.r2.b.value = field_storage.r2.b;
|
|
||||||
assign hwif_out.r2.b.ored = |(field_storage.r2.b);
|
|
||||||
// Field: test_regblock.r2.c
|
|
||||||
always_comb begin
|
|
||||||
field_combo.r2.c.next = field_storage.r2.c;
|
|
||||||
field_combo.r2.c.load_next = '0;
|
|
||||||
if(decoded_reg_strb.r2 && decoded_req_is_wr) begin // SW write
|
|
||||||
field_combo.r2.c.next = decoded_wr_data[23:16];
|
|
||||||
field_combo.r2.c.load_next = '1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if(rst) begin
|
|
||||||
field_storage.r2.c <= 'h30;
|
|
||||||
end else if(field_combo.r2.c.load_next) begin
|
|
||||||
field_storage.r2.c <= field_combo.r2.c.next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign hwif_out.r2.c.value = field_storage.r2.c;
|
|
||||||
assign hwif_out.r2.c.swmod = decoded_reg_strb.r2 && decoded_req_is_wr;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Readback
|
// Readback
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
logic readback_err;
|
logic readback_err;
|
||||||
logic readback_done;
|
logic readback_done;
|
||||||
logic [DATA_WIDTH-1:0] readback_data;
|
logic [31:0] readback_data;
|
||||||
logic [DATA_WIDTH-1:0] readback_array[3];
|
|
||||||
|
|
||||||
assign readback_array[0][7:0] = (decoded_reg_strb.r0 && !decoded_req_is_wr) ? field_storage.r0.a : '0;
|
// Assign readback values to a flattened array
|
||||||
assign readback_array[0][15:8] = (decoded_reg_strb.r0 && !decoded_req_is_wr) ? field_storage.r0.b : '0;
|
logic [31:0] readback_array[112];
|
||||||
assign readback_array[0][23:16] = (decoded_reg_strb.r0 && !decoded_req_is_wr) ? field_storage.r0.c : '0;
|
for(genvar i0=0; i0<112; i0++) begin
|
||||||
assign readback_array[0][31:24] = '0;
|
assign readback_array[i0*1 + 0][7:0] = (decoded_reg_strb.r2[i0] && !decoded_req_is_wr) ? field_storage.r2[i0].a : '0;
|
||||||
assign readback_array[1][7:0] = (decoded_reg_strb.r1 && !decoded_req_is_wr) ? field_storage.r1.a : '0;
|
assign readback_array[i0*1 + 0][31:8] = '0;
|
||||||
assign readback_array[1][15:8] = (decoded_reg_strb.r1 && !decoded_req_is_wr) ? field_storage.r1.b : '0;
|
end
|
||||||
assign readback_array[1][23:16] = (decoded_reg_strb.r1 && !decoded_req_is_wr) ? field_storage.r1.c : '0;
|
|
||||||
assign readback_array[1][31:24] = '0;
|
|
||||||
assign readback_array[2][7:0] = (decoded_reg_strb.r2 && !decoded_req_is_wr) ? field_storage.r2.a : '0;
|
|
||||||
assign readback_array[2][15:8] = (decoded_reg_strb.r2 && !decoded_req_is_wr) ? field_storage.r2.b : '0;
|
|
||||||
assign readback_array[2][23:16] = (decoded_reg_strb.r2 && !decoded_req_is_wr) ? field_storage.r2.c : '0;
|
|
||||||
assign readback_array[2][31:24] = '0;
|
|
||||||
|
|
||||||
|
|
||||||
|
// Reduce the array
|
||||||
always_comb begin
|
always_comb begin
|
||||||
automatic logic [DATA_WIDTH-1:0] readback_data_var;
|
automatic logic [31:0] readback_data_var;
|
||||||
readback_done = decoded_req & ~decoded_req_is_wr;
|
readback_done = decoded_req & ~decoded_req_is_wr;
|
||||||
readback_err = '0;
|
readback_err = '0;
|
||||||
|
|
||||||
readback_data_var = '0;
|
readback_data_var = '0;
|
||||||
for(int i=0; i<3; i++) begin
|
for(int i=0; i<112; i++) readback_data_var |= readback_array[i];
|
||||||
readback_data_var |= readback_array[i];
|
|
||||||
end
|
|
||||||
readback_data = readback_data_var;
|
readback_data = readback_data_var;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if(rst) begin
|
if(rst) begin
|
||||||
cpuif_rd_ack <= '0;
|
cpuif_rd_ack <= '0;
|
||||||
@@ -369,4 +166,5 @@ module test_regblock (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
@@ -1,85 +1,19 @@
|
|||||||
// TODO: Add a banner
|
// TODO: Add a banner
|
||||||
package test_regblock_pkg;
|
package test_regblock_pkg;
|
||||||
|
|
||||||
// test_regblock.r0.a
|
// test_regblock.r2[].a
|
||||||
typedef struct {
|
typedef struct {
|
||||||
logic [7:0] value;
|
logic [7:0] value;
|
||||||
logic anded;
|
logic anded;
|
||||||
} test_regblock__r0__a__out_t;
|
} test_regblock__r2x__a__out_t;
|
||||||
|
|
||||||
// test_regblock.r0.b
|
// test_regblock.r2[]
|
||||||
typedef struct {
|
typedef struct {
|
||||||
logic [7:0] value;
|
test_regblock__r2x__a__out_t a;
|
||||||
logic ored;
|
} test_regblock__r2x__out_t;
|
||||||
} test_regblock__r0__b__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r0.c
|
|
||||||
typedef struct {
|
|
||||||
logic [7:0] value;
|
|
||||||
logic swmod;
|
|
||||||
} test_regblock__r0__c__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r0
|
|
||||||
typedef struct {
|
|
||||||
test_regblock__r0__a__out_t a;
|
|
||||||
test_regblock__r0__b__out_t b;
|
|
||||||
test_regblock__r0__c__out_t c;
|
|
||||||
} test_regblock__r0__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r1.a
|
|
||||||
typedef struct {
|
|
||||||
logic [7:0] value;
|
|
||||||
logic anded;
|
|
||||||
} test_regblock__r1__a__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r1.b
|
|
||||||
typedef struct {
|
|
||||||
logic [7:0] value;
|
|
||||||
logic ored;
|
|
||||||
} test_regblock__r1__b__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r1.c
|
|
||||||
typedef struct {
|
|
||||||
logic [7:0] value;
|
|
||||||
logic swmod;
|
|
||||||
} test_regblock__r1__c__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r1
|
|
||||||
typedef struct {
|
|
||||||
test_regblock__r1__a__out_t a;
|
|
||||||
test_regblock__r1__b__out_t b;
|
|
||||||
test_regblock__r1__c__out_t c;
|
|
||||||
} test_regblock__r1__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r2.a
|
|
||||||
typedef struct {
|
|
||||||
logic [7:0] value;
|
|
||||||
logic anded;
|
|
||||||
} test_regblock__r2__a__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r2.b
|
|
||||||
typedef struct {
|
|
||||||
logic [7:0] value;
|
|
||||||
logic ored;
|
|
||||||
} test_regblock__r2__b__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r2.c
|
|
||||||
typedef struct {
|
|
||||||
logic [7:0] value;
|
|
||||||
logic swmod;
|
|
||||||
} test_regblock__r2__c__out_t;
|
|
||||||
|
|
||||||
// test_regblock.r2
|
|
||||||
typedef struct {
|
|
||||||
test_regblock__r2__a__out_t a;
|
|
||||||
test_regblock__r2__b__out_t b;
|
|
||||||
test_regblock__r2__c__out_t c;
|
|
||||||
} test_regblock__r2__out_t;
|
|
||||||
|
|
||||||
// test_regblock
|
// test_regblock
|
||||||
typedef struct {
|
typedef struct {
|
||||||
test_regblock__r0__out_t r0;
|
test_regblock__r2x__out_t r2[112];
|
||||||
test_regblock__r1__out_t r1;
|
|
||||||
test_regblock__r2__out_t r2;
|
|
||||||
} test_regblock__out_t;
|
} test_regblock__out_t;
|
||||||
endpackage
|
endpackage
|
||||||
9
test/vlog_args.f
Normal file
9
test/vlog_args.f
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-quiet
|
||||||
|
|
||||||
|
# Free version of ModelSim errors if generate statements are not used.
|
||||||
|
# These have been made optional long ago. Modern versions of SystemVerilog do
|
||||||
|
# not require them.
|
||||||
|
-suppress 2720
|
||||||
|
|
||||||
|
# Ignore warning about vopt-time checking of always_comb/always_latch
|
||||||
|
-suppress 2583
|
||||||
@@ -15,7 +15,7 @@ add wave -noupdate /tb/dut/cpuif_req
|
|||||||
add wave -noupdate /tb/dut/cpuif_req_is_wr
|
add wave -noupdate /tb/dut/cpuif_req_is_wr
|
||||||
add wave -noupdate /tb/dut/cpuif_addr
|
add wave -noupdate /tb/dut/cpuif_addr
|
||||||
add wave -noupdate /tb/dut/cpuif_wr_data
|
add wave -noupdate /tb/dut/cpuif_wr_data
|
||||||
add wave -noupdate /tb/dut/cpuif_wr_bitstrb
|
add wave -noupdate /tb/dut/cpuif_wr_biten
|
||||||
add wave -noupdate /tb/dut/cpuif_rd_ack
|
add wave -noupdate /tb/dut/cpuif_rd_ack
|
||||||
add wave -noupdate /tb/dut/cpuif_rd_data
|
add wave -noupdate /tb/dut/cpuif_rd_data
|
||||||
add wave -noupdate /tb/dut/cpuif_rd_err
|
add wave -noupdate /tb/dut/cpuif_rd_err
|
||||||
|
|||||||
Reference in New Issue
Block a user