This commit creates a new top level wrapping the core, register file and
icache RAMs. The tracing top level is also renamed to ibex_top_tracing
to match. This new top level is intended to enable a dual core lockstep
implementation of Ibex.
There are no functional changes in this commit, only wiring.
Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
The -Wwarn-IMPERFECTSCH flag is suggested in the Verilator docs (to
help spot if we get a clock gating hint wrong). The waiver is no
longer needed because we now add the relevant hint in the
RTL (vendored in prim_generic_clock_gating.sv from OpenTitan).
- Move various unused signal fixes from the waiver file to the rtl, so
that all tools can pick them up.
- Fix some oversize line issues.
- Fix some signed / unsigned casting issues.
- Remove some extraneous semicolons.
Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
- This change should have no functional impact on the design
- Adding the separate module will allow easy parameterization
of security hardening for individual CSRs in the future
- As a side benefit, clock gating is added for CSRs that didn't
previously have it
- Note that this change makes the cpuctrl register always present,
rather than individual bits being added depending on parameterized
features. This is not ideal, but the parameterization becomes rather
messy otherwise.
Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
Verible lint now supports waivers without regex and line arguments. Use
this new feature and remove the workaround we had in place.
Signed-off-by: Philipp Wagner <phw@lowrisc.org>
The waiver files currently don't support comments, and require the
"empty" regex; bugs have been filed to get that resolved upstream.
But beyond that, waivers are now functional.
This commit contains some final optimizations regarding the bit
manipulation extension as well as the parametrization into a balanced
version and a full performance version.
Balanced Version:
* Supports ZBB, ZBS, ZBF and ZBT extensions
* Dual cycle instructions:
ror[i], rol, cmov, cmix fsl, fsr[i]
* Everything else completes in a single cycle.
Full Version:
* Supports all 32b sub extensions.
* Dual cycle instructions:
ror[i], rol, cmov, cmix fsl, fsr[i], crc32[c], bext, bdep
* Everything else completes in a single cycle.
Notable Changes:
* bext/bdep are now multi-cycle: Sharing additional register
with multiplier module
* grev/gorc instructions are implemented in separate structures
rather than sharing the shifter or butterfly network.
* Speed up decision on using rs1 or rs3 for alu_operand_a by
introducing single-bit register, to identify ternary
instructions in their first cycle.
* Introduce enumerated parameter to chose bit manipulation
implementation
Signed-off-by: ganoam <gnoam@live.com>
Instead of using copies of primitives from OpenTitan, vendor the files
in directly from OpenTitan, and use them.
Benefits:
- Less potential for diverging code between OpenTitan and Ibex, causing
problems when importing Ibex into OT.
- Use of the abstract primitives instead of the generic ones. The
abstract primitives are replaced during synthesis time with
target-dependent implementations. For simulation, nothing changes. For
synthesis for a given target technology (e.g. a specific ASIC or FPGA
technology), the primitives system can be instructed to choose
optimized versions (if available).
This is most relevant for the icache, which hard-coded the generic
SRAM primitive before. This primitive is always implemented as
registers. By using the abstract primitive (prim_ram_1p) instead, the
RAMs can be replaced with memory-compiler-generated ones if necessary.
There are no real draw-backs, but a couple points to be aware of:
- Our ram_1p and ram_2p implementations are kept as wrapper around the
primitives, since their interface deviates slightly from the one in
prim_ram*. This also includes a rather unfortunate naming confusion
around rvalid, which means "read data valid" in the OpenTitan advanced
RAM primitives (prim_ram_1p_adv for example), but means "ack" in
PULP-derived IP and in our bus implementation.
- The core_ibex UVM DV doesn't use FuseSoC to generate its file list,
but uses a hard-coded list in `ibex_files.f` instead. Since the
dynamic primitives system requires the use of FuseSoC we need to
provide a stop-gap until this file is removed. Issue #893 tracks
progress on that.
- Dynamic primitives depend no a not-yet-merged feature of FuseSoC
(https://github.com/olofk/fusesoc/pull/391). We depend on the same
functionality in OpenTitan and have instructed users to use a patched
branch of FuseSoC for a long time through `python-requirements.txt`,
so no action is needed for users which are either successfully
interacting with the OpenTitan source code, or have followed our
instructions. All other users will see a reasonably descriptive error
message during a FuseSoC run.
- This commit is massive, but there are no good ways to split it into
bisectable, yet small, chunks. I'm sorry. Reviewers can safely ignore
all code in `vendor/lowrisc_ip`, it's an import from OpenTitan.
- The check_tool_requirements tooling isn't easily vendor-able from
OpenTitan at the moment. I've filed
https://github.com/lowRISC/opentitan/issues/2309 to get that sorted.
- The LFSR primitive doesn't have a own core file, forcing us to include
the catch-all `lowrisc:prim:all` core. I've filed
https://github.com/lowRISC/opentitan/issues/2310 to get that sorted.
This commit implements the Bit Manipulation Extension SBS instruction
group: sbset[i], sbclr[i], sbinv[i] and sbext[i]. These instructions
set, clear, invert or extract bit rs1[rs2] or rs1[imm] for reg-reg and
reg-imm instructions respectively.
Archtectural details:
* A multiplexer is added to the shifter structure in order to
chose between 32'h1, used for the single-bit instructions as
summarized below, and regular operand_b input.
* Dedicated bitwise-logic blocks are introduced for multicycle
shifts and cmix instructions (fsr, fsl, ror, rol),
single-bit instructions (sbset, sbclr, sbinv, sbext), and
stanard-ALU and zbb instructions (or, and xor, orn, andn,
xnor).
Instruction details: All of the zbs instructions rely on sharing the
existing shifter structure. The instructions are carried out in
one cycle.
* sbset, sbclr, sbinv:
shift_result = 32'h1 << rs2[4:0];
singlebit_result = rs1 [|, ^ , &~] shift_result;
* sbext:
shift_result = rs1 >> rs2[4:0];
singlebit_result = {31'0,shift_resutl[0]};
Signed-off-by: ganoam <gnoam@live.com>
This commits implements the Bit Manipulateion Extension ZBT instruction
group: cmix, cmov, fsr[i] and fsl. Those are instructions depend on
three ALU operands. Completeion of these instructions takes 2 clock
cycles. Additionally, the rotation shifts rol and ror are made
multicycle instructions.
All multicycle instructions take exactly two cycles to complete.
Architectural additions:
* Multicycle Stage Register in ID stage.
multicycle_op_stage_reg
* Decoder generates alu_multicycle signal, to stall pipeline
* For all ternary instructions:
1. cycle: connect alu operands a and b to rs1 and rs2
respectively
2. cycle: connect operands a and be to rs3 and rs2
respectively
* Reduce the physical size of the shifter from 64 bit to 63
bit: 32-bit operand + 1 bit for arithmetic / one-shift
* Make rotation shifts multicycle instructions.
Instruction Details:
* cmov:
1. store operand a (rs1) in stage reg.
2. return stage reg output (rs2) or rs3.
if rs2 != 0 the output (rs1) is already known in the
first cycle. -> variable latency implementation is
possible.
* cmix:
1. store rs1 & rs2 in stage reg
2. return stage_reg_q | (rs2 & ~rs3)
reusing bwlogic from zbb
* rol/ror: (here: ror)
shift_amt = rs2 & 31;
shift_amt_compl = (32 - shift_amt) & 31
1. store (rs1 >> shift_amt) in stage reg
2. return (rs1 << shift_amt_compl) | stage_reg_q
* fsl/fsr:
For funnel shifts, the order of applying the shift
amount or its complement is determined by bit [5] of
shift_amt. Pseudocode for fsr:
shift_amt = rs2 & 63
shift_amt_compl = (32 - shift_amt[4:0])
1. if (shift_amt >= 33):
store (rs1 >> shift_amt_compl[4:0]) in stage reg
else if (shift_amt <0 && shift_amt <= 31):
store (rs1 << shift_amt[4:0]) in stage reg
else if (shift_amt == 32 || shift_amt == 0):
store rs1 in stage reg
2. if (shift_amt >= 33):
return stage_reg_q | (rs3 << shift_amt[4:0])
else if (shift_amt <0 && shift_amt <= 31):
return stage_reg_q | (rs3 >> shift_amt_compl[4:0])
else if (shift_amt == 32):
return rs3
else if (shift_amt == 0):
return rs1
Signed-off-by: ganoam <gnoam@live.com>
- A new parameter and a run-time control bit (DataIndTiming and
data_ind_timing) enabling different behaviour for running security critical
code sections.
- In the new mode, all branches act as if taken, with not-taken
branches executing as a branch to the next instruction.
- This should give similar execution time/power characteristics
regardless of the branch condition.
- Note that with the BranchTargetALU, branches stall an extra cycle in
secure mode to avoid factoring the branch-taken decision into the
branch target address mux.
Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
This commit implements the Bit Manipulation Extension ZBB instruction
group: clz, ctz, pcnt, slo, sro, rol, ror, rev, rev8, orcb, pack
packu, packh, min, max, andn, orn, and xnor.
* Bit counting instructions clz, ctz and pcnt can be implemented to
share much of the architecture:
clz: Count Leading Zeros. Counts the number of 0 bits at the
MSB end of the argument.
ctz: Count Trailing Zeros. Counts the number of 0 bits at the
LSB end of the argument.
pcnt: Counts the number of set bits of the argument.
The implementation uses:
- 32 one bit adders, counting the set bits of a signal
bitcnt_bits, starting from the LSB end.
- For pcnt the argument is fed directly into bitcnt_bits.
- For clz, the operand is reversed such that leading zeros are
located at the LSB end of bitcnt_bits.
- For ctz and clz: counter enable signal for 1-bit counter i
is high, if the previous enable signal, and
its corresponting bitcnt_bit was high.
* Instructions sll[i], srl[i],slo[i], sro[i], rol, ror[i], rev, rev8
and orc.b are summarized as shifting instructions and related:
The following instructions are slight variations of the
existing base spec's sll, srl and sra instructions.
- slo[i] and sro[i]: shift left/right ones: similar to
shift-logical operations from base spec, but shifting
in ones instead of zeros.
- rol and ror[i]: rotate left/right ones: circular shift
operations. shifting in values from the oposite end
of the operand instead of zeros.
Those instructions can be implemented, sharing the base spec's
shifting structure. In order to support rotate operations, a
64-bit shifting structure is needed.
In the existing ALU, hardware is described only for right
shifts. For left shifts the operand is initially reversed,
right shifted and the result is reversed back. This gives rise
to an additional resource sharing oportunity for some more
zbb operations:
- rev: bitwise reversal.
- rev8: byte-order swap.
- orc.b: byte-wise reverse and or-combine.
* Instructions min, max:
For the B-extension's min/max instructions, we can share the
existing comparison operations. The result is obtained by
activating the comparison structure accordingly and
multiplexing the operands using the comparison result.
* Logic-with-negate instructions andn, orn, xnor:
For the B-extension's logic-with-negate instructions we can
share the structures of the base spec's logic structures
already present for 'xnor', 'or' and 'and' instructions as
well as the conditionally negated b operand generated for
subtraction operations.
* Instructions pack, packu, packh:
For the pack, packh and packu instructions I don't see any
opportunities for resource sharing. However, the architecture
is quite simple.
- pack: pack the lower halves of rs1 and rs2 into rd, with rs1
in the lower half and rs2 in the upper half.
- packu: pack the upper halves of rs1 and rs2 into rd, with
rs1 in the lower half and rs2 in the upper half.
- packh: pack the LSB bytes of rs1 and rs2 into rd, with rs1
in the lower half and rs2 in the upper half.
Signed-off-by: ganoam <gnoam@live.com>
Verilator will soon support the configuration file syntax of wildcard
matches for linter warnings to waive. Switch to the new syntax that
avoids line-based rule settings.
Use of case inside in always_ff block does not meet style guide
recomendations. Refactored to remove this.
Signed-off-by: Greg Chadwick <gac@lowrisc.org>
* Integrate option to implement a multiplier using 3 parallel 17 bit
multipliers in order to compute MUL instructions in 1 cycle
MULH in 2 cycles.
* Add parameter SingleCycleMultiply to select single cycle
multiplication.
The single cycle multiplication capability is intended for FPGA
targets. Using three parallel multiplication units improves performance
of multiplication operations at the cost of DSP primitives. For ASIC
targets, the area consumed by the multiplication structure will grow
approximately 3-4x.
The functionality is selected within the module using the parameter
`SingleCycleMultiply`. From the top level it can be chosen by setting
the parameter `MultiplierImplementation` to 'single_cc'.
Signed-off-by: ganoam <gnoam@live.com>
This commit modifies the `mip` CSR to not depend on the `mie` CSR. While
the values of both these CSRs are combined to decide whether an
interrupt shall be handled, the RISC-V spec does not state that the
content of of `mip` should depend on `mie`. This commit better aligns
Ibex with other open-source RISC-V cores.
This resolveslowRISC/ibex#567 reported by @pfmooney.
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
multdiv_sel signals the mult/div operand should be selected for the ALU
inputs. Previously the mult_en/div_en signals were used but these factor
in whether the instruction is actually happening which is not relevant
for the mux select. The dedicated select signal gives better timing.
Adds a second set of instruction flops that are used to determine ALU
operation and operand selection. This reduces fanout from the
instruction flops and so helps timing.
prim_assert.sv is a file containing assertion macros (defines).
Previously, prim_assert.sv was compiled as normal SystemVerilog file.
This made the defines available for the whole compilation unit as soon
as they were defined. Since all cores using prim_assert depended (in
fusesoc) on the lowrisc:prim:assert core, prim_assert was always
compiled first, and the defines were visible in subsequent files.
All of that is only true if all files end up in one comilation unit. The
SV standard states that what makes up a compilation unit is
tool-defined, but also states that typically, passing multiple files (or
a file list/.f file) to a single tool invocation means that all files
end up in one compilation unit; if the tool is called multiple times,
then the files end up in separate compilation units.
Edalize (the fusesoc backend) doesn't guarantee either behavior, and so
it happens that for Vivado, Verilator, Cadence and Synopsys simulators,
all files are compiled into a single compilation unit. But for Riviera,
each file is a separate compilation unit.
To avoid relying on the definition of compilation units, and to do the
generally right thing (TM), this commit changes the code to always
include the prim_assert.sv file when it is used in a source file.
Include guards are introduced in the prim_assert.sv file to avoid
defining things twice.
This commit adds a register file designed to be synthesized into FPGA
synchronous-write / asynchronous-read design elements.
For the artya7-100 example, the register file is implemented by 12
RAM32M primitives, conserving approximately 600 Logic LUTs and 1000
flip-flops at the expense of 48 LUTRAMs.
Signed-off-by: ganoam <gnoam@live.com>
This commit replaces all X assignments in the RTL with defined
values. In addition, SystemVerilog Assertions are added to catch
invalid signal values in simulation. A new file containing the
corresponding assertion macros is added as well.
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
- Add the minimum amount of trigger system to support GDB hbreak
- Only a single trigger is implemented
- Only instruction address matching
- Only break into debug mode (no native debug)
- Fixes#382
Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
This commit reworks the generation of the `core_busy` signal used to
control the main clock gate of the core. Without this commit, the
controller generates a separate `first_fetch` signal only asserted in
the FIRST_FETCH state that directly controls `core_busy` and thus the
main clock gate. This is problematic as it introduces a feedback to
from the controller state into the clock.
This commit removes the problematic signal and changes the generation of
`ctrl_busy` in the FIRST_FETCH state of the controller. This signal is
now used to control the main clock gate in all states (previously all
except FIRST_FETCH) but it gets registered, thus it does not introduce
the feedback into the clock.
This resolveslowRISC/ibex#211.
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
These operations (ALU_SLET, ALU_SLETU) are remnants of of the original
OpenRISC design. RISC-V just has set-less-than (ALU_SLT, ALU_SLTU).
This resolveslowRISC/ibex#432 reported by @udinator.
These operations (ALU_GT, ALU_GTU, ALU_LE, ALU_LEU) are remnants of
of the original OpenRISC design. RISC-V does not have these instructions
and instead implements the operations by reversing operands for ALU_LT,
ALU_LTU, ALU_GE, ALU_GEU.
This resolveslowRISC/ibex#420 reported by @udinator.
- The RISC-V Debug Spec v.0.13.2 (p.41) mandates that the core
debug CSRs dcsr, dpc, dscratch0 and dscratch1 must not be
accessible if not in debug mode. Fixes#275
- Instantiate generic PMP module
- Wire up I-side and D-side PMP faults
- The output of the PMP check is used to gate external bus requests from the
I-side and LSU
- Each of those units progresses with their request as-if it was granted
externally and registers the PMP error
- The error is then sent to the controller at the appropriate time to trigger
an exception