Skip to content

Instantly share code, notes, and snippets.

@dhouck
Created January 20, 2018 08:10
Show Gist options
  • Save dhouck/ecdeca32606815ef363a1a8389661cc9 to your computer and use it in GitHub Desktop.
Save dhouck/ecdeca32606815ef363a1a8389661cc9 to your computer and use it in GitHub Desktop.
Microcode for Ben Eater's breadboard computer at https://www.youtube.com/playlist?list=PLowKtXNTBypGqImE405J2565dvjafglHU
#include <cstddef>
#include <array>
#include <stdexcept>
//// This would be a header file if Compiler Explorer supported those
//// You can skip to the comment "Instructions set definition here"
// Use put in a namespace to avoid poluting global namespace (Otherwise there are issues with multiple HLTs)
namespace ControlBitsNS {
enum ControlBits : uint16_t {
NONE = 0,
J = 1 << 1,
CO = 1 << 2,
CE = 1 << 3,
OI = 1 << 4,
BI = 1 << 5,
SU = 1 << 6,
EO = 1 << 7,
AO = 1 << 8,
AI = 1 << 9,
II = 1 << 10,
IO = 1 << 11,
RO = 1 << 12,
RI = 1 << 13,
MI = 1 << 14,
HLT = 1 << 15
};
// Make the bitwise operators return the right type
ControlBits constexpr operator|(ControlBits lhs, ControlBits rhs) {
return ControlBits(uint16_t(lhs) | uint16_t(rhs));
}
ControlBits constexpr operator&(ControlBits lhs, ControlBits rhs) {
return ControlBits(uint16_t(lhs) & uint16_t(rhs));
}
ControlBits constexpr operator~(ControlBits bits) {
return ControlBits(~ uint16_t(bits));
}
}
using ControlBitsNS::ControlBits;
/// Verify that control bits are sensible
ControlBits constexpr verify(ControlBits uop) {
ControlBits output_ops = ControlBits::CO | ControlBits::EO | ControlBits::AO
| ControlBits::IO | ControlBits::RO;
ControlBits input_ops = ControlBits::J | ControlBits::OI | ControlBits::BI
| ControlBits::AI | ControlBits::II | ControlBits::RI
| ControlBits::MI;
if (__builtin_popcount(uint16_t(uop & output_ops)) > 1) {
throw std::invalid_argument("Contention on the bus");
}
if ((uop & output_ops) && ! (uop & input_ops)) {
throw std::invalid_argument("Bus output not being read");
}
if ((uop & input_ops) && ! (uop & output_ops)) {
throw std::invalid_argument("Reading floating bus input");
}
// Note: We do not check that HLT is the only control bit if it's set
// You might want to halt in subtract mode or with soething on the bus.
return uop;
}
struct Microcode {
constexpr Microcode(ControlBits t2 = ControlBits::NONE, ControlBits t3 = ControlBits::NONE,
ControlBits t4 = ControlBits::NONE, ControlBits t5 = ControlBits::NONE,
ControlBits t6 = ControlBits::NONE, ControlBits t7 = ControlBits::NONE)
: uops{{verify(t2), verify(t3), verify(t4), verify(t5), verify(t6), verify(t7)}} {}
// Initialization microcode; same for every instruction
std::array<ControlBits, 2> init {{verify(ControlBits::MI | ControlBits::CO),
verify(ControlBits::II | ControlBits::RO | ControlBits::CE)}};
std::array<ControlBits, 6> uops;
};
static_assert(sizeof(Microcode) == 16, "Microcode object size incorrect");
using InstructionSet = std::array<Microcode, 16>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment