Add passthrough CPUIF

This commit is contained in:
Alex Mykyta
2022-01-27 22:04:17 -08:00
parent ae9d555ef4
commit 321d8a6cd1
12 changed files with 161 additions and 14 deletions

View File

@@ -1,6 +1,3 @@
{% extends "cpuif/base_tmpl.sv" %}
{% block body %}
// Request
logic is_active;
always_ff {{get_always_ff_event(cpuif.reset)}} begin
@@ -36,4 +33,3 @@ end
assign {{cpuif.signal("pready")}} = cpuif_rd_ack | cpuif_wr_ack;
assign {{cpuif.signal("prdata")}} = cpuif_rd_data;
assign {{cpuif.signal("pslverr")}} = cpuif_rd_err | cpuif_wr_err;
{%- endblock body%}

View File

@@ -7,7 +7,7 @@ if TYPE_CHECKING:
from systemrdl import SignalNode
class CpuifBase:
template_path = "cpuif/base_tmpl.sv"
template_path = ""
def __init__(self, exp:'RegblockExporter', cpuif_reset:Optional['SignalNode'], data_width:int=32, addr_width:int=32):
self.exp = exp

View File

@@ -1,2 +0,0 @@
{%- block body %}
{%- endblock %}

View File

@@ -0,0 +1,19 @@
from ..base import CpuifBase
class PassthroughCpuif(CpuifBase):
template_path = "cpuif/passthrough/passthrough_tmpl.sv"
@property
def port_declaration(self) -> str:
lines = [
"input wire s_cpuif_req",
"input wire s_cpuif_req_is_wr",
f"input wire [{self.addr_width-1}:0] s_cpuif_addr",
f"input wire [{self.data_width-1}:0] s_cpuif_wr_data",
"output wire s_cpuif_rd_ack",
"output wire s_cpuif_rd_err",
f"output wire [{self.data_width-1}:0] s_cpuif_rd_data",
"output wire s_cpuif_wr_ack",
"output wire s_cpuif_wr_err",
]
return ",\n".join(lines)

View File

@@ -0,0 +1,9 @@
assign cpuif_req = s_cpuif_req;
assign cpuif_req_is_wr = s_cpuif_req_is_wr;
assign cpuif_addr = s_cpuif_addr;
assign cpuif_wr_data = s_cpuif_wr_data;
assign s_cpuif_rd_ack = cpuif_rd_ack;
assign s_cpuif_rd_err = cpuif_rd_err;
assign s_cpuif_rd_data = cpuif_rd_data;
assign s_cpuif_wr_ack = cpuif_wr_ack;
assign s_cpuif_wr_err = cpuif_wr_err;

View File

@@ -106,7 +106,6 @@ class RegblockExporter:
context = {
"module_name": module_name,
"user_out_of_hier_signals": scanner.out_of_hier_signals.values(),
"interrupts": [], # TODO:
"cpuif": self.cpuif,
"hwif": self.hwif,
"get_resetsignal": self.dereferencer.get_resetsignal,

View File

@@ -11,10 +11,6 @@ module {{module_name}} (
{%- endif %}
{%- endfor %}
{%- for interrupt in interrupts %}
// TODO:
{%- endfor %}
{{cpuif.port_declaration|indent(8)}}
{%- if hwif.has_input_struct or hwif.has_output_struct %},{% endif %}
@@ -30,8 +26,8 @@ module {{module_name}} (
logic [{{cpuif.data_width-1}}:0] cpuif_wr_data;
logic cpuif_rd_ack;
logic [{{cpuif.data_width-1}}:0] cpuif_rd_data;
logic cpuif_rd_err;
logic [{{cpuif.data_width-1}}:0] cpuif_rd_data;
logic cpuif_wr_ack;
logic cpuif_wr_err;

View File

@@ -0,0 +1,10 @@
from ..base import CpuifTestMode
from peakrdl.regblock.cpuif.passthrough import PassthroughCpuif
class Passthrough(CpuifTestMode):
cpuif_cls = PassthroughCpuif
tb_files = [
"passthrough_driver.sv",
]
tb_template = "tb_inst.sv"

View File

@@ -0,0 +1,92 @@
interface passthrough_driver #(
parameter DATA_WIDTH = 32,
parameter ADDR_WIDTH = 32
)(
input wire clk,
input wire rst,
output logic m_cpuif_req,
output logic m_cpuif_req_is_wr,
output logic [ADDR_WIDTH-1:0] m_cpuif_addr,
output logic [DATA_WIDTH-1:0] m_cpuif_wr_data,
input wire m_cpuif_rd_ack,
input wire m_cpuif_rd_err,
input wire [DATA_WIDTH-1:0] m_cpuif_rd_data,
input wire m_cpuif_wr_ack,
input wire m_cpuif_wr_err
);
timeunit 1ps;
timeprecision 1ps;
default clocking cb @(posedge clk);
default input #1step output #1;
output m_cpuif_req;
output m_cpuif_req_is_wr;
output m_cpuif_addr;
output m_cpuif_wr_data;
input m_cpuif_rd_ack;
input m_cpuif_rd_err;
input m_cpuif_rd_data;
input m_cpuif_wr_ack;
input m_cpuif_wr_err;
endclocking
task reset();
cb.m_cpuif_req <= '0;
cb.m_cpuif_req_is_wr <= '0;
cb.m_cpuif_addr <= '0;
cb.m_cpuif_wr_data <= '0;
endtask
task write(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] data);
##0;
// Initiate transfer
cb.m_cpuif_req <= '1;
cb.m_cpuif_req_is_wr <= '1;
cb.m_cpuif_addr <= addr;
cb.m_cpuif_wr_data <= data;
@(cb);
reset();
// Wait for response
while(cb.m_cpuif_wr_ack !== 1'b1) @(cb);
reset();
endtask
task read(logic [ADDR_WIDTH-1:0] addr, output logic [DATA_WIDTH-1:0] data);
##0;
// Initiate transfer
cb.m_cpuif_req <= '1;
cb.m_cpuif_req_is_wr <= '0;
cb.m_cpuif_addr <= addr;
@(cb);
reset();
// Wait for response
while(cb.m_cpuif_rd_ack !== 1'b1) @(cb);
assert(!$isunknown(cb.m_cpuif_rd_data)) else $error("Read from 0x%0x returned X's on m_cpuif_rd_data", addr);
data = cb.m_cpuif_rd_data;
reset();
endtask
task assert_read(logic [ADDR_WIDTH-1:0] addr, logic [DATA_WIDTH-1:0] expected_data, logic [DATA_WIDTH-1:0] mask = '1);
logic [DATA_WIDTH-1:0] data;
read(addr, data);
data &= mask;
assert(data == expected_data) else $error("Read from 0x%x returned 0x%x. Expected 0x%x", addr, data, expected_data);
endtask
initial begin
reset();
end
initial forever begin
@cb;
if(!rst) assert(!$isunknown(cb.m_cpuif_rd_ack)) else $error("Saw X on m_cpuif_rd_ack!");
if(!rst) assert(!$isunknown(cb.m_cpuif_wr_ack)) else $error("Saw X on m_cpuif_wr_ack!");
end
endinterface

View File

@@ -0,0 +1,26 @@
{% sv_line_anchor %}
wire s_cpuif_req;
wire s_cpuif_req_is_wr;
wire [{{exporter.cpuif.addr_width-1}}:0] s_cpuif_addr;
wire [{{exporter.cpuif.data_width-1}}:0] s_cpuif_wr_data;
wire s_cpuif_rd_ack;
wire s_cpuif_rd_err;
wire [{{exporter.cpuif.data_width-1}}:0] s_cpuif_rd_data;
wire s_cpuif_wr_ack;
wire s_cpuif_wr_err;
passthrough_driver #(
.DATA_WIDTH({{exporter.cpuif.data_width}}),
.ADDR_WIDTH({{exporter.cpuif.addr_width}})
) cpuif (
.clk(clk),
.rst(rst),
.m_cpuif_req(s_cpuif_req),
.m_cpuif_req_is_wr(s_cpuif_req_is_wr),
.m_cpuif_addr(s_cpuif_addr),
.m_cpuif_wr_data(s_cpuif_wr_data),
.m_cpuif_rd_ack(s_cpuif_rd_ack),
.m_cpuif_rd_err(s_cpuif_rd_err),
.m_cpuif_rd_data(s_cpuif_rd_data),
.m_cpuif_wr_ack(s_cpuif_wr_ack),
.m_cpuif_wr_err(s_cpuif_wr_err)
);

View File

@@ -1,11 +1,13 @@
from itertools import product
from .cpuifs.apb3 import APB3, FlatAPB3
from .cpuifs.passthrough import Passthrough
all_cpuif = [
APB3(),
FlatAPB3(),
Passthrough(),
]
def get_permutations(spec):