Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multiaddr_decode: Add default port logic #235

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 71 additions & 11 deletions src/multiaddr_decode.sv
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
/// is set.
/// For each rule, it also returns the subset of addresses in {`addr_i`, `mask_i`} which
/// match the rule {`addr_o[i]`, `mask_o[i]`}.
///
/// There is the possibility to add a default mapping:
/// `en_default_idx_i`: Driving this port to `1'b1` maps all input addresses
/// for which no rule in `addr_map_i` exists to the default index specified by
/// `default_idx_i`. In this case, `dec_error_o` is always `1'b0`.
/// Note: `default_idx_i` must carry the rule representing the union of all other
/// rules' address sets, in order to determine if any address in the input address
/// doesn't fall in the address set of any rule.
module multiaddr_decode #(
/// Highest index which can happen in a rule.
parameter int unsigned NoIndices = 32'd0,
Expand Down Expand Up @@ -60,7 +68,16 @@ module multiaddr_decode #(
/// to the {addr, mask} representation (and viceversa) using the following equations:
/// - mask = {'0, {log2(end - start){1'b1}}}
/// - addr = start
parameter type rule_t = logic
parameter type rule_t = logic,
/// Dependent parameter, do **not** overwite!
///
/// Width of the `default_idx_i` input port.
parameter int unsigned IdxWidth = cf_math_pkg::idx_width(NoIndices),
/// Dependent parameter, do **not** overwite!
///
/// Type of the `default_idx_i` input port.
parameter type idx_t = logic [IdxWidth-1:0]

) (
/// Multi-address to decode.
input addr_t addr_i,
Expand All @@ -75,19 +92,35 @@ module multiaddr_decode #(
/// Decode is valid.
output logic dec_valid_o,
/// Decode is not valid, no matching rule found.
output logic dec_error_o
output logic dec_error_o,
/// Enable default port mapping.
///
/// When not used, tie to `0`.
input logic en_default_idx_i,
/// Default port rule.
///
/// When `en_default_idx_i` is `1`, this containes the index when the input doesn't
/// fully match the other rules. To easily determine if this is the case, this signal
/// carries the rule representing the union of all other rules. This is not the default
/// slave's rule but actually its complement.
///
/// When not used, tie to `0`.
input rule_t default_idx_i
);

logic [NoRules-1:0] matched_rules; // purely for address map debugging

always_comb begin
// default assignments
matched_rules = '0;
dec_valid_o = 1'b0;
dec_error_o = 1'b1;
select_o = '0;
addr_o = '0;
mask_o = '0;
matched_rules = '0;
dec_valid_o = 1'b0;
dec_error_o = en_default_idx_i ? 1'b0 : 1'b1;
select_o = '0;
// input address and mask are propagated unchanged to the default slave
addr_o = '0;
mask_o = '0;
addr_o[default_idx_i.idx] = en_default_idx_i ? addr_i : '0;
mask_o[default_idx_i.idx] = en_default_idx_i ? mask_i : '0;

// Match the rules
for (int unsigned i = 0; i < NoRules; i++) begin
Expand Down Expand Up @@ -117,6 +150,14 @@ module multiaddr_decode #(
addr_o[idx] = (~mask_i & addr_i) | (mask_i & addr_map_i[i].addr);
end
end
// Match the default slave rule
// An input address set is fully contained in a rule's address set if there is a
// match (dec_valid_o) and there are no masked bits in the input address set which
// are not masked also in the rule's address set.
// If the input address set is not fully contained in the union of all rules'
// address sets, forward to default slave.
if (en_default_idx_i)
select_o[default_idx_i.idx] = (!dec_valid_o || |(mask_i & ~default_idx_i.mask));
end

// Assumptions and assertions
Expand All @@ -132,18 +173,37 @@ module multiaddr_decode #(
end

// These following assumptions check the validity of the address map.
// check_idx: Enforces a valid index in the rule.
always @(addr_map_i) #0 begin : proc_check_addr_map
// check_default_idx: Enforces a valid default idx.
// check_rule_idx: Enforces a valid index in the rule.
// check_rule_idx_default: Checks that no rule contains the default index.
always @(addr_map_i, en_default_idx_i, default_idx_i) #0 begin : proc_check_addr_map
if (!$isunknown(addr_map_i)) begin
if (en_default_idx_i) begin
check_default_idx : assume (default_idx_i.idx < NoIndices) else
$fatal(1, $sformatf("Default index value is not allowed!!!\n\
IDX: %h\n\
MAX_IDX: %h\n\
#####################################################",
default_idx_i.idx, (NoIndices-1)));
end
for (int unsigned i = 0; i < NoRules; i++) begin
// check the SLV ids
check_idx : assume (addr_map_i[i].idx < NoIndices) else
check_rule_idx : assume (addr_map_i[i].idx < NoIndices) else
$fatal(1, $sformatf("This rule has a IDX that is not allowed!!!\n\
Violating rule %d.\n\
Rule> IDX: %h\n\
Rule> MAX_IDX: %h\n\
#####################################################",
i, addr_map_i[i].idx, (NoIndices-1)));
if (en_default_idx_i) begin
check_rule_idx_default : assume (addr_map_i[i].idx != default_idx_i.idx) else
$fatal(1, $sformatf("This rule has a IDX that is not allowed!!!\n\
Violating rule %d.\n\
Index: %h\n\
Default index> : %h\n\
#####################################################",
i, addr_map_i[i].idx, default_idx_i.idx));
end
end
end
end
Expand Down
Loading